home *** CD-ROM | disk | FTP | other *** search
/ 3D GFX / 3D GFX.iso / amiutils / i_l / irit5 / irit / inptevl2.c < prev    next >
C/C++ Source or Header  |  1995-12-30  |  27KB  |  785 lines

  1. /*****************************************************************************
  2. *   "Irit" - the 3d (not only polygonal) solid modeller.             *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.2, Mar. 1990   *
  5. ******************************************************************************
  6. *   Module to evaluate the binary tree generated by the InptPrsr module.     *
  7. *   All the objects are handled the same but the numerical one, which is     *
  8. * moved as a RealType and not as an object (only internally within this         *
  9. * module) as it is frequently used and consumes much less memory this way.   *
  10. *   Note this module is par of InptPrsr module and was splited only because  *
  11. * of text file sizes problems...                         *
  12. *****************************************************************************/
  13.  
  14. #include <stdio.h>
  15. #include <ctype.h>
  16. #include <math.h>
  17. #include <string.h>
  18. #include "program.h"
  19. #include "allocate.h"
  20. #include "attribut.h"
  21. #include "convex.h"
  22. #include "ctrl-brk.h"
  23. #include "dosintr.h"
  24. #include "freeform.h"
  25. #include "geomat3d.h"
  26. #include "geomvals.h"
  27. #include "inptprsg.h"
  28. #include "inptprsl.h"
  29. #include "objects.h"
  30. #include "overload.h"
  31. #include "primitiv.h"
  32. #include "windows.h"
  33. #include "iritgrap.h"
  34.  
  35. InptPrsrEvalErrType
  36.     IPGlblEvalError = IPE_NO_ERR;         /* Global used by EvalTree. */
  37.  
  38. static void LocalPrintTree(ParseTree *Root, int Level, char *Str);
  39.  
  40. /*****************************************************************************
  41. * DESCRIPTION:                                                               M
  42. * Returns a string representing the given type.                     M
  43. *                                                                            *
  44. * PARAMETERS:                                                                M
  45. *   Type:     Type to get a string representation for.                       M
  46. *                                                                            *
  47. * RETURN VALUE:                                                              M
  48. *   char *:   A string describing type Type.                                 M
  49. *                                                                            *
  50. * KEYWORDS:                                                                  M
  51. *   InptPrsrTypeToStr                                                        M
  52. *****************************************************************************/
  53. char *InptPrsrTypeToStr(IritExprType Type)
  54. {
  55.     switch (Type) {
  56.     case POLY_EXPR:
  57.         return "Poly";
  58.     case NUMERIC_EXPR:
  59.         return "Numeric";
  60.     case POINT_EXPR:
  61.         return "Point";
  62.     case VECTOR_EXPR:
  63.         return "Vector";
  64.     case PLANE_EXPR:
  65.         return "Plane";
  66.     case CTLPT_EXPR:
  67.         return "Control Point";
  68.     case MATRIX_EXPR:
  69.         return "Matrix";
  70.     case STRING_EXPR:
  71.         return "String";
  72.     case OLST_EXPR:
  73.         return "List Object";
  74.     case CURVE_EXPR:
  75.         return "Curve";
  76.     case SURFACE_EXPR:
  77.         return "Surface";
  78.     default:
  79.         return "Undefined";
  80.     }
  81.  
  82. }
  83.  
  84. /*****************************************************************************
  85. * DESCRIPTION:                                                               M
  86. * Counts the number of parameters in Root. Parameters are defined as         M
  87. * subtrees seperated by commas, i.e.: the infix form 1, 2, 3, 4 is          M
  88. * represented as [1, [2, [3, 4]]] in the tree supplied to this function and  M
  89. * 4 (number of parameters) is returned.                         M
  90. *                                                                            *
  91. * PARAMETERS:                                                                M
  92. *   Root:      To count the number of its parameters.                        M
  93. *                                                                            *
  94. * RETURN VALUE:                                                              M
  95. *   int:       Number of parameters encountered.                             M
  96. *                                                                            *
  97. * KEYWORDS:                                                                  M
  98. *   InptEvalCountNumParameters                                               M
  99. *****************************************************************************/
  100. int InptEvalCountNumParameters(ParseTree *Root)
  101. {
  102.     int i = 1;
  103.  
  104.     if (Root == NULL)
  105.     return 0;
  106.  
  107.     while (Root -> NodeKind == COMMA) {
  108.     i++;
  109.     Root = Root -> Right;
  110.     }
  111.     return i;
  112. }
  113.  
  114. /*****************************************************************************
  115. * DESCRIPTION:                                                               M
  116. * Fetches the i'th paramter out of a tree represent n parameters             M
  117. * (0 <= i < n). See InptEvalCountNumParameters for more description of         M
  118. * structure.                                     M
  119. * Note it is assumed the tree HAS n parameters and 0<=i<n (No input error).  M
  120. *                                                                            *
  121. * PARAMETERS:                                                                M
  122. *   Root:     To fetch its i'th parameter.                                   M
  123. *   i:        The parameter wanted.                                          M
  124. *   n:        Total number of parameters in Root.                            M
  125. *                                                                            *
  126. * RETURN VALUE:                                                              M
  127. *   ParseTree *:    The requested parameter.                                 M
  128. *                                                                            *
  129. * KEYWORDS:                                                                  M
  130. *   InptEvalFetchParameter                                                   M
  131. *****************************************************************************/
  132. ParseTree *InptEvalFetchParameter(ParseTree *Root, int i, int n)
  133. {
  134.     int j;
  135.  
  136.     for (j = 0; j < i; j++)
  137.     Root = Root -> Right;
  138.  
  139.     if (i == n - 1)
  140.     return Root;
  141.     else
  142.     return Root -> Left;
  143. }
  144.  
  145. /*****************************************************************************
  146. * DESCRIPTION:                                                               M
  147. * Fetches the parameters of a function from the parsed tree.             M
  148. * Returns TRUE iff fetching was succesfull.                     M
  149. *                                                                            *
  150. * PARAMETERS:                                                                M
  151. *   Root:          Where the parameters should be searched for.              M
  152. *   FuncTable:     The table's entry of the function we deal with.           M
  153. *   NumParams:     Number of parameters of function.                         M
  154. *   Level:         Level of recursion. To identify top levels.               M
  155. *   Params:        Where to put the parameters as ParseTree.                 M
  156. *   ParamPtrs:     And as pointers to RealType/PointType/VectorType etc.     M
  157. *                                                                            *
  158. * RETURN VALUE:                                                              M
  159. *   int:           If everything matches.                                    M
  160. *                                                                            *
  161. * KEYWORDS:                                                                  M
  162. *   InptEvalFetchParameters                                                  M
  163. *****************************************************************************/
  164. int InptEvalFetchParameters(ParseTree *Root,
  165.                 FuncTableType *FuncTable,
  166.                 int NumParams,
  167.                 int Level,
  168.                 ParseTree *Params[],
  169.                 VoidPtr ParamPtrs[])
  170. {
  171.     int i;
  172.  
  173.     Level++;
  174.     for (i = 0; i < NumParams; i++) {
  175.     if ((Params[i] = InptPrsrEvalTree(InptEvalFetchParameter(Root -> Right,
  176.                                  i, NumParams),
  177.                       Level)) == NULL)
  178.         return i;
  179.  
  180.     if (FuncTable != NULL) {
  181.         if (FuncTable -> ParamObjType[i] == NUMERIC_EXPR)
  182.         ParamPtrs[i] = &Params[i] -> PObj -> U.R;
  183.         else if (FuncTable -> ParamObjType[i] == POINT_EXPR)
  184.         ParamPtrs[i] = Params[i] -> PObj -> U.Pt;
  185.         else if (FuncTable -> ParamObjType[i] == VECTOR_EXPR)
  186.         ParamPtrs[i] = Params[i] -> PObj -> U.Vec;
  187.         else if (FuncTable -> ParamObjType[i] == CTLPT_EXPR)
  188.         ParamPtrs[i] = &Params[i] -> PObj -> U.CtlPt;
  189.         else if (FuncTable -> ParamObjType[i] == PLANE_EXPR)
  190.         ParamPtrs[i] = Params[i] -> PObj -> U.Plane;
  191.         else if (FuncTable -> ParamObjType[i] == STRING_EXPR)
  192.         ParamPtrs[i] = Params[i] -> PObj -> U.Str;
  193.         else
  194.         ParamPtrs[i] = Params[i] -> PObj;
  195.     }
  196.     }
  197.  
  198.     return i;
  199. }
  200.  
  201. /*****************************************************************************
  202. * DESCRIPTION:                                                               M
  203. * Tests number of parameters and type of them against what is defined in the M
  204. * global tables Num/Obj/GenFuncTable. return TRUE if mismatch was detected.  M
  205. *                                                                            *
  206. * PARAMETERS:                                                                M
  207. *   Root:     The function entry node.                                       M
  208. *                                                                            *
  209. * RETURN VALUE:                                                              M
  210. *   int:      TRUE if a mismatch wasdetected, FALSE of o.k.             N
  211. *                                                                            *
  212. * KEYWORDS:                                                                  M
  213. *   IritEvalFuncParamMismatch                                                M
  214. *****************************************************************************/
  215. int IritEvalFuncParamMismatch(ParseTree *Root)
  216. {
  217.     int FuncOffset, Count,
  218.     i = Root -> NodeKind / 100;
  219.     FuncTableType *FuncTable;
  220.  
  221.     switch (i * 100) {
  222.     case NUM_FUNC:               /* Numeric (real returned) functions. */
  223.         FuncOffset = Root -> NodeKind - NUM_FUNC_OFFSET;
  224.         FuncTable = (FuncTableType *) NumFuncTable;
  225.         break;
  226.     case OBJ_FUNC1:                 /* Object (returned) functions. */
  227.     case OBJ_FUNC2:                 /* Object (returned) functions. */
  228.         FuncOffset = Root -> NodeKind - OBJ_FUNC_OFFSET;
  229.         FuncTable = (FuncTableType *) ObjFuncTable;
  230.         break;
  231.     case GEN_FUNC:
  232.         FuncOffset = Root -> NodeKind - GEN_FUNC_OFFSET;
  233.         FuncTable = (FuncTableType *) GenFuncTable;
  234.         break;
  235.     default:
  236.         IPGlblEvalError = IE_ERR_FATAL_ERROR;
  237.         UpdateCharError("Undefined function - ", Root -> NodeKind, Root);
  238.         return TRUE;
  239.     }
  240.  
  241.     Count = InptEvalCountNumParameters(Root -> Right);
  242.  
  243.     if (FuncTable[FuncOffset].NumOfParam == ANY_PARAM_NUM) {
  244.     for (i = 0; i < Count; i++) {
  245.         IritExprType EType;
  246.  
  247.         /* Special cases - FORLOOP and IF - top level considerations. */
  248.         if ((Root -> NodeKind == FORLOOP && i == 3) ||
  249.         (Root -> NodeKind == IFCOND && i > 0))
  250.         EType = InptPrsrTypeCheck(InptEvalFetchParameter(Root -> Right,
  251.                                  i, Count), 0);
  252.         else
  253.         EType = InptPrsrTypeCheck(InptEvalFetchParameter(Root -> Right,
  254.                                  i, Count), 1);
  255.  
  256.         /* Check only for consistency of input. */
  257.         if (EType == ERROR_EXPR)
  258.         return TRUE;
  259.     }
  260.     return FALSE;
  261.     }
  262.     else { /* Number of parameter is well known and is in Count. */
  263.     /* See if number of parameters is ok: */
  264.     if (Count != FuncTable[FuncOffset].NumOfParam) {
  265.         IPGlblEvalError = IE_ERR_NUM_PRM_MISMATCH;
  266.         sprintf(IPGlblCharData, "Func %s - %d expected, %d found",
  267.             FuncTable[FuncOffset].FuncName,
  268.             FuncTable[FuncOffset].NumOfParam,
  269.             Count);
  270.         return TRUE;
  271.     }
  272.  
  273.     /* See if type of parameters are consistent: */
  274.     for (i = 0; i < Count; i++) {
  275.         IritExprType EType;
  276.  
  277.         /* Special cases - FORLOOP and IF - top level considerations. */
  278.         if ((Root -> NodeKind == FORLOOP && i == 3) ||
  279.         (Root -> NodeKind == IFCOND && i > 0))
  280.         EType = InptPrsrTypeCheck(InptEvalFetchParameter(Root -> Right,
  281.                                  i, Count), 0);
  282.         else
  283.         EType = InptPrsrTypeCheck(InptEvalFetchParameter(Root -> Right,
  284.                                  i, Count), 1);
  285.  
  286.         if (EType == ERROR_EXPR)
  287.         return TRUE;
  288.         if (FuncTable[FuncOffset].ParamObjType[i] != ANY_EXPR &&
  289.         !(FuncTable[FuncOffset].ParamObjType[i] & EType)) {
  290.         sprintf(IPGlblCharData, "Func %s,%sparameter %d",
  291.             FuncTable[FuncOffset].FuncName,
  292.             IPGlblEvalError == IE_ERR_IP_OBJ_UNDEFINED ?
  293.                         " undefined " : " ", i + 1);
  294.         IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
  295.         return TRUE;
  296.         }
  297.     }
  298.     return FALSE;
  299.     }
  300. }
  301.  
  302. /*****************************************************************************
  303. * DESCRIPTION:                                                               M
  304. * Deallocates a parsed tree - release all memory allocated by it.         M
  305. *                                                                            *
  306. * PARAMETERS:                                                                M
  307. *   Root:      Of tree to release.                                           M
  308. *                                                                            *
  309. * RETURN VALUE:                                                              M
  310. *   void                                                                     M
  311. *                                                                            *
  312. * KEYWORDS:                                                                  M
  313. *   InptPrsrFreeTree                                                         M
  314. *****************************************************************************/
  315. void InptPrsrFreeTree(ParseTree *Root)
  316. {
  317.     char s[LINE_LEN];
  318.  
  319.     if (!Root)
  320.     return;
  321.  
  322.     if (IS_FUNCTION(Root -> NodeKind)) {
  323.     if (IS_NO_PARAM_FUNC(Root -> NodeKind))
  324.         ExprFree(Root);
  325.     else {
  326.         InptPrsrFreeTree(Root -> Right);
  327.         if (Root -> PObj != NULL && strlen(Root -> PObj -> Name) == 0)
  328.         IPFreeObject(Root -> PObj);             /* Its temp.*/
  329.         ExprFree(Root);
  330.         }
  331.     return;
  332.     }
  333.  
  334.     switch (Root -> NodeKind) {
  335.     case DIV:
  336.     case MINUS:
  337.     case MULT:
  338.     case PLUS:
  339.     case POWER:
  340.         InptPrsrFreeTree(Root -> Right);
  341.         InptPrsrFreeTree(Root -> Left);
  342.         if (Root -> PObj != NULL && strlen(Root -> PObj -> Name) == 0)
  343.         IPFreeObject(Root -> PObj);             /* Its tmp. */
  344.         ExprFree(Root);
  345.         break;
  346.  
  347.     case UNARMINUS:
  348.     case BOOL_NOT:
  349.         InptPrsrFreeTree(Root -> Right);
  350.         if (Root -> PObj != NULL && strlen(Root -> PObj -> Name) == 0)
  351.         IPFreeObject(Root -> PObj);             /* Its tmp. */
  352.         ExprFree(Root);
  353.         break;
  354.  
  355.     case COMMA:
  356.     case COLON:
  357.     case EQUAL:
  358.     case CMP_EQUAL:
  359.     case CMP_NOTEQUAL:
  360.     case CMP_LSEQUAL:
  361.     case CMP_GTEQUAL:
  362.     case CMP_LESS:
  363.     case CMP_GREAT:
  364.     case BOOL_OR:
  365.     case BOOL_AND:
  366.           InptPrsrFreeTree(Root -> Right);
  367.         InptPrsrFreeTree(Root -> Left);
  368.         ExprFree(Root);
  369.         break;
  370.  
  371.     case PARAMETER:
  372.         if (Root -> PObj) {
  373.         /* If object is not part of global variable list - remove it.*/
  374.         if (strlen(Root -> PObj -> Name) == 0)
  375.             IPFreeObject(Root -> PObj);
  376.         else
  377.             Root -> PObj -> Count--;
  378.         }
  379.         ExprFree(Root);
  380.         break;
  381.  
  382.     case NUMBER:
  383.     case STRING:
  384.         if (Root -> PObj)
  385.         IPFreeObject(Root -> PObj);
  386.         ExprFree(Root);
  387.         break;
  388.  
  389.     case TOKENSTART:
  390.         ExprFree(Root);
  391.         break;
  392.  
  393.     case OPENPARA:
  394.     case CLOSPARA:
  395.         ExprFree(Root);
  396.         break;
  397.  
  398.     default:
  399.         /*   We might free partially build (by InptPrsr) tree when error */
  400.         /* is detected, and such tree may have nodes with NodeKind>=1000.*/
  401.         if (Root -> NodeKind >= 1000) {
  402.         ExprFree(Root);
  403.         }
  404.         else {
  405.         sprintf(s, "%s (%d).\n",
  406.             "InptPrsrFreeTree: Undefined ParseTree type to free",
  407.             Root -> NodeKind);
  408.         IritFatalError(s);
  409.         }
  410.         break;
  411.     }
  412. }
  413.  
  414. /*****************************************************************************
  415. * DESCRIPTION:                                                               M
  416. * Prints the content of ROOT (using inorder traversal).                 M
  417. * If *Str = NULL prints on stderr, else on given string Str.             *
  418. *                                                                            *
  419. * PARAMETERS:                                                                M
  420. *   Root:      Of tree to print.                                             M
  421. *   Str:       String to write on the inorder of Root, or stderr if NULL.    M
  422. *                                                                            *
  423. * RETURN VALUE:                                                              M
  424. *   void                                                                     M
  425. *                                                                            *
  426. * KEYWORDS:                                                                  M
  427. *   InptPrsrPrintTree                                                        M
  428. *****************************************************************************/
  429. void InptPrsrPrintTree(ParseTree *Root, char *Str)
  430. {
  431.     strcpy(IPGlblCharData, "");               /* Make the string empty. */
  432.  
  433.     if (Str == NULL) {
  434.     strcpy(IPGlblCharData, "");           /* Make the string empty. */
  435.     LocalPrintTree(Root, 0, IPGlblCharData);       /* Copy to local str. */
  436.     fprintf(stderr, IPGlblCharData);             /* and print... */
  437.     }
  438.     else {
  439.     strcpy(Str, "");               /* Make the string empty. */
  440.     LocalPrintTree(Root, 0, Str); /* Dont print to stderr - copy to str. */
  441.     }
  442. }
  443.  
  444. /*****************************************************************************
  445. * DESCRIPTION:                                                               *
  446. * Auxiliary function of InptPrsrPrintTree.                     *
  447. *  It is assumed Str has at least INPUT_LINE_LEN places to write the         *
  448. * expression.                                     *
  449. *                                                                            *
  450. * PARAMETERS:                                                                *
  451. *   Root:      Of tree to print.                                             *
  452. *   Level:     Of recursion.                                                 *
  453. *   Str:       String to write on the inorder of Root, or stderr if NULL.    *
  454. *                                                                            *
  455. * RETURN VALUE:                                                              *
  456. *   void                                                                     *
  457. *****************************************************************************/
  458. static void LocalPrintTree(ParseTree *Root, int Level, char *Str)
  459. {
  460.     int Len, i,
  461.     CloseFlag = FALSE;
  462.  
  463.     if (!Root)
  464.     return;
  465.     i = Root -> NodeKind / 100;
  466.  
  467.     if ((Len = strlen(Str)) > INPUT_LINE_LEN + 100)     /* Prevent overflow. */
  468.     if (Str[Len - 1] == '.')
  469.         return;             /* "..." was allready concatenated. */
  470.     else {
  471.         strcat(Str, "...");
  472.         return;
  473.     }
  474.  
  475. #   ifdef DEBUG1
  476.     strcat(Str, "[");   /* Usefull to see ALL nestings - no preceedings. */
  477. #   endif /* DEBUG1 */
  478.  
  479.     switch (i * 100) {
  480.     case USER_FUNC:
  481.         switch (Root -> NodeKind) {
  482.         case USERFUNCDEF:
  483.             Level = 0;
  484.             CloseFlag = TRUE;
  485.             strcat(Str, "function(");
  486.             break;
  487.         case USERPROCDEF:
  488.             Level = 0;
  489.             CloseFlag = TRUE;
  490.             strcat(Str, "procedure(");
  491.             break;
  492.         case USERINSTDEF:
  493.             Level = 0;
  494.             CloseFlag = TRUE;
  495.             strcat(Str, Root -> UserFunc -> FuncName);
  496.             strcat(Str, "(");
  497.             break;
  498.         }
  499.         break;
  500.  
  501.     case NUM_FUNC:
  502.         Level = 0;
  503.         CloseFlag = TRUE;
  504.             strcat(Str,
  505.            NumFuncTable[Root -> NodeKind - NUM_FUNC_OFFSET].FuncName);
  506.         strcat(Str, "(");
  507.         break;
  508.  
  509.     case OBJ_FUNC1:
  510.     case OBJ_FUNC2:
  511.         Level = 0;
  512.         CloseFlag = TRUE;
  513.             strcat(Str,
  514.            ObjFuncTable[Root -> NodeKind - OBJ_FUNC_OFFSET].FuncName);
  515.         strcat(Str, "(");
  516.         break;
  517.  
  518.     case GEN_FUNC:
  519.         Level = 0;
  520.         CloseFlag = TRUE;
  521.             strcat(Str,
  522.            GenFuncTable[Root -> NodeKind - GEN_FUNC_OFFSET].FuncName);
  523.         strcat(Str, "(");
  524.         break;
  525.  
  526.     case OPERATORS:
  527.         switch (Root -> NodeKind) {
  528.         case DIV:
  529.             if (Level > 1) {
  530.             strcat(Str, "(");
  531.                 CloseFlag = TRUE;
  532.             }
  533.             Level = 1;                       /* Div Level. */
  534.             LocalPrintTree(Root -> Left, Level, Str);
  535.             strcat(Str, "/");
  536.             break;
  537.  
  538.         case MINUS:
  539.             if (Level > 0) {
  540.             strcat(Str, "(");
  541.                 CloseFlag = TRUE;
  542.             }
  543.             Level = 0;                     /* Minus Level. */
  544.             LocalPrintTree(Root -> Left, Level, Str);
  545.             strcat(Str, "-");
  546.             break;
  547.  
  548.         case MULT:
  549.             if (Level > 1) {
  550.             strcat(Str, "(");
  551.                 CloseFlag = TRUE;
  552.             }
  553.             Level = 1;                       /* Mul Level. */
  554.             LocalPrintTree(Root -> Left, Level, Str);
  555.             strcat(Str, "*");
  556.             break;
  557.  
  558.         case PLUS:
  559.             if (Level > 0) {
  560.             strcat(Str, "(");
  561.                 CloseFlag = TRUE;
  562.             }
  563.             Level = 0;                      /* Plus Level. */
  564.             LocalPrintTree(Root -> Left, Level, Str);
  565.             strcat(Str, "+");
  566.             break;
  567.  
  568.         case POWER:
  569.             Level = 2;                     /* Power Level. */
  570.             LocalPrintTree(Root -> Left, Level, Str);
  571.             strcat(Str, "^");
  572.             break;
  573.  
  574.         case UNARMINUS:
  575.             strcat(Str, "(-");
  576.             Level = 0;
  577.             CloseFlag = TRUE;
  578.             break;
  579.  
  580.         case COMMA:
  581.             LocalPrintTree(Root -> Left, Level, Str);
  582.             strcat(Str, ",");
  583.             break;
  584.  
  585.         case COLON:
  586.             LocalPrintTree(Root -> Left, Level, Str);
  587.             strcat(Str, ":");
  588.             break;
  589.  
  590.         case EQUAL:
  591.             LocalPrintTree(Root -> Left, Level, Str);
  592.             strcat(Str, "=");
  593.             break;
  594.  
  595.         case CMP_EQUAL:
  596.             LocalPrintTree(Root -> Left, Level, Str);
  597.             strcat(Str, "==");
  598.             break;
  599.  
  600.         case CMP_NOTEQUAL:
  601.             LocalPrintTree(Root -> Left, Level, Str);
  602.             strcat(Str, "!=");
  603.             break;
  604.  
  605.         case CMP_LSEQUAL:
  606.             LocalPrintTree(Root -> Left, Level, Str);
  607.             strcat(Str, "<=");
  608.             break;
  609.  
  610.         case CMP_GTEQUAL:
  611.             LocalPrintTree(Root -> Left, Level, Str);
  612.             strcat(Str, ">=");
  613.             break;
  614.  
  615.         case CMP_LESS:
  616.             LocalPrintTree(Root -> Left, Level, Str);
  617.             strcat(Str, "<");
  618.             break;
  619.  
  620.         case CMP_GREAT:
  621.             LocalPrintTree(Root -> Left, Level, Str);
  622.             strcat(Str, ">");
  623.             break;
  624.  
  625.         case BOOL_OR:
  626.             LocalPrintTree(Root -> Left, Level, Str);
  627.             strcat(Str, "||");
  628.             break;
  629.  
  630.         case BOOL_AND:
  631.             LocalPrintTree(Root -> Left, Level, Str);
  632.             strcat(Str, "&&");
  633.             break;
  634.  
  635.         case BOOL_NOT:
  636.             LocalPrintTree(Root -> Left, Level, Str);
  637.             strcat(Str, "!");
  638.             break;
  639.  
  640.         case NUMBER:
  641.             sprintf(&Str[strlen(Str)], "%g", Root -> PObj -> U.R);
  642.             break;
  643.  
  644.         case PARAMETER:
  645.             sprintf(&Str[strlen(Str)], "%s", Root -> PObj -> Name);
  646.             break;
  647.  
  648.         case STRING:
  649.             sprintf(&Str[strlen(Str)], "\"%s\"",
  650.                 Root -> PObj -> U.Str);
  651.             break;
  652.  
  653.         case OPENPARA:
  654.             strcat(Str, "(");
  655.             break;
  656.  
  657.         case CLOSPARA:
  658.             strcat(Str, ")");
  659.             break;
  660.  
  661.         case TOKENSTART:
  662.             break;
  663.  
  664.         default:
  665.             IritFatalError("LocalPrintTree: Undefined ParseTree type to print, exit");
  666.             }
  667.             break;
  668.  
  669.     default:
  670.         IritFatalError("LocalPrintTree: Undefined ParseTree type to print, exit");
  671.     }
  672.     LocalPrintTree(Root -> Right, Level, Str);
  673.     if (CloseFlag)
  674.     strcat(Str, ")");
  675.  
  676. #   ifdef DEBUG1
  677.     strcat(Str, "]");   /* Usefull to see ALL nestings - no preceedings. */
  678. #   endif /* DEBUG1 */
  679. }
  680.  
  681. /*****************************************************************************
  682. * DESCRIPTION:                                                               M
  683. * Duplicates a parse tree - Generates brand new ParseTree structure but      M
  684. * binds to non-temp variables if they are exists - their Name is not NULL.   M
  685. *   This means that updating these objects in the copied tree, will affect   M
  686. * these objects in the original tree.                         M
  687. *                                                                            *
  688. * PARAMETERS:                                                                M
  689. *   Root:     To duplicate.                                                  M
  690. *                                                                            *
  691. * RETURN VALUE:                                                              M
  692. *   ParseTree *:   Duplicated parse tree                                     M
  693. *                                                                            *
  694. * KEYWORDS:                                                                  M
  695. *   InptPrsrCopyTree                                                         M
  696. *****************************************************************************/
  697. ParseTree *InptPrsrCopyTree(ParseTree *Root)
  698. {
  699.     ParseTree *NewRoot;
  700.  
  701.     if (Root == NULL)
  702.     return NULL;
  703.  
  704.     NewRoot = ExprMalloc();
  705.  
  706.     if (IS_FUNCTION(Root -> NodeKind)) {           /* All the functions. */
  707.     NewRoot -> NodeKind = Root -> NodeKind;
  708.     NewRoot -> Right = InptPrsrCopyTree(Root -> Right);
  709.     if (IS_USER_FUNCTION(Root -> NodeKind))
  710.         NewRoot -> UserFunc = Root -> UserFunc;
  711.     return NewRoot;
  712.     }
  713.  
  714.     switch (Root -> NodeKind) {
  715.     case DIV:
  716.     case MINUS:
  717.     case MULT:
  718.     case PLUS:
  719.     case POWER:
  720.  
  721.     case COMMA:
  722.     case COLON:
  723.     case EQUAL:
  724.     case CMP_EQUAL:
  725.     case CMP_NOTEQUAL:
  726.     case CMP_LSEQUAL:
  727.     case CMP_GTEQUAL:
  728.     case CMP_LESS:
  729.     case CMP_GREAT:
  730.         case BOOL_OR:
  731.         case BOOL_AND:
  732.         NewRoot -> NodeKind = Root -> NodeKind;
  733.         NewRoot -> Right = InptPrsrCopyTree(Root -> Right);
  734.         NewRoot -> Left  = InptPrsrCopyTree(Root -> Left);
  735.         return NewRoot;
  736.  
  737.     case UNARMINUS:
  738.         case BOOL_NOT:
  739.         NewRoot -> NodeKind = Root -> NodeKind;
  740.         NewRoot -> Right = InptPrsrCopyTree(Root -> Right);
  741.         NewRoot -> Left  = NULL;
  742.         return NewRoot;
  743.  
  744.     case NUMBER:
  745.     case PARAMETER:
  746.     case STRING:
  747.         NewRoot -> NodeKind = Root -> NodeKind;
  748.         NewRoot -> PObj = Root -> PObj;        /* Point on SAME object. */
  749.         NewRoot -> PObj -> Count++;      /* But increase its ref. count. */
  750.         return NewRoot;
  751.  
  752.     case TOKENSTART:
  753.         NewRoot -> NodeKind = Root -> NodeKind;
  754.         return NewRoot;
  755.  
  756.     default:
  757.         IritFatalError("InptPrsrCopyTree: Undefined ParseTree type to copy, exit");
  758.     }
  759.     return NULL;                    /* Makes warning silent. */
  760. }
  761.  
  762. /*****************************************************************************
  763. * DESCRIPTION:                                                               M
  764. * Routine to return evaluation error if happen one, zero elsewhere         M
  765. *                                                                            *
  766. * PARAMETERS:                                                                M
  767. *   Message:    Place here a message describing an error, if was one.        M
  768. *                                                                            *
  769. * RETURN VALUE:                                                              M
  770. *   InptPrsrEvalErrType:  Type of evaluation error.                          M
  771. *                                                                            *
  772. * KEYWORDS:                                                                  M
  773. *   InptPrsrEvalError                                                        M
  774. *****************************************************************************/
  775. InptPrsrEvalErrType InptPrsrEvalError(char **Message)
  776. {
  777.     InptPrsrEvalErrType Temp;
  778.  
  779.     *Message = IPGlblCharData;
  780.     Temp = IPGlblEvalError;
  781.     IPGlblEvalError = IPE_NO_ERR;
  782.  
  783.     return Temp;
  784. }
  785.